/**
@file

@brief

@author
	GengYong
@revision
	2005/11/05 * Created by GengYong.
*/


#include "StdUtility.h"
#include "KernelImpl.h"
#include "ModuleManager.h"
#include <cassert>

using namespace SAF;

KernelImpl::KernelImpl(unsigned long maxMessageRouterCount, unsigned long maxServiceModuleCount, unsigned long maxStateCount)
:m_maxCountOfMessageRouter(maxMessageRouterCount)
,m_maxCountOfServiceModule(maxServiceModuleCount)
,m_maxCountOfState(maxStateCount)
,m_messageRouterList(0), m_serviceModuleList(0)
,m_messageRouterRoot(0), m_serviceModuleRoot(0)
,m_stateNameRoot(0)
,m_serviceModuleDiffList(0), m_serviceModuleStateTable(0), m_serviceModuleCatalogId(0)
,m_messageRouterInitState(0)
,m_countOfMessageRouter(0), m_countOfServiceModule(0)
,m_countOfState(0)
{
	PERFCOUNTER("KernelImpl::KernelImpl");

	assert(m_maxCountOfMessageRouter > 0);
	assert(m_maxCountOfServiceModule > 0);
	assert(m_maxCountOfState > 0);

	m_messageRouterList			=	new IMessageRouter*[m_maxCountOfMessageRouter];
	m_serviceModuleList			=	new IServiceModule*[m_maxCountOfServiceModule];
	m_messageRouterInitState	=	new int[m_maxCountOfMessageRouter];
	m_serviceModuleCatalogId	=	new int[m_maxCountOfServiceModule];
	m_serviceModuleStateTable	=	new StateBits[m_maxCountOfServiceModule];
	m_serviceModuleDiffList		=	new KernelImpl::ServiceModuleList[m_maxCountOfState * m_maxCountOfState];

	for (int index = 0; index < m_maxCountOfMessageRouter; index++)
	{
		m_messageRouterList[index]		= 0;
		m_messageRouterInitState[index]	= (unsigned long)(-1);
	}

	for (int index = 0; index < m_maxCountOfServiceModule; index++)
	{
		m_serviceModuleList[index]			= 0;
		m_serviceModuleStateTable[index]	= 0;
		m_serviceModuleCatalogId[index]		= 0;
	}

	for (int index = 0; index < (m_maxCountOfState * m_maxCountOfState); index++)
	{
		m_serviceModuleDiffList[index].list		= 0;
		m_serviceModuleDiffList[index].count	= 0;
	}
	return;
}

KernelImpl::~KernelImpl()
{
	PERFCOUNTER("KernelImpl::~KernelImpl");

	struct MessageRouterTreeDestroyer
	{	
		MessageRouterTreeDestroyer(KernelImpl * const This, KernelImpl::ModuleTree * node)
		{
			PERFCOUNTER("KernelImpl::~KernelImpl::MessageDeviceTreeDestroyer");

			if (node != 0)
			{
				MessageRouterTreeDestroyer DestroyLeft(This, node->lleaf);
				MessageRouterTreeDestroyer DestroyRight(This, node->rleaf);
				
				(void)DestroyLeft;
				(void)DestroyRight;

				KernelImpl::HookList * point = node->hooks;
				KernelImpl::HookList * nexthook = 0;
				for (; point != 0; point = nexthook)
				{
					if (point->messageRouterHook != 0)
					{
						(*(point->messageRouterHook))(node->messageRouter, 0, point->cbdata);
					}
					nexthook = point->next;
					point->next = 0;
					delete point;
				}

				node->messageRouter->Release();
				ModuleManager::Instance().DestroyObject(node->name, node->messageRouter);

				Util::Util_FreeString(node->name);
				delete node;
			}
			return;
		}
	} DestroyMessageRouterTree(this, m_messageRouterRoot);

	(void)DestroyMessageRouterTree;

	this->m_messageRouterRoot = 0;

	struct ServiceModuleTreeDestroyer
	{
		ServiceModuleTreeDestroyer(KernelImpl * const This, KernelImpl::ModuleTree * node)
		{
			PERFCOUNTER("KernelImpl::~KernelImpl::ServiceModuleTreeDestroyer");

			if (node != 0)
			{
				ServiceModuleTreeDestroyer DestroyLeft(This, node->lleaf);
				ServiceModuleTreeDestroyer DestroyRight(This, node->rleaf);
				
				(void)DestroyLeft;
				(void)DestroyRight;

				KernelImpl::HookList * point = node->hooks;
				KernelImpl::HookList * nexthook = 0;
				for (; point != 0; point = nexthook)
				{
					if (point->messageRouterHook != 0)
					{
						(*(point->serviceModuleHook))(node->serviceModule, 0, point->cbdata);
					}
					nexthook = point->next;
					point->next = 0;
					delete point;
				}

				node->serviceModule->Release();
				ModuleManager::Instance().DestroyObject(node->name, node->serviceModule);

				Util::Util_FreeString(node->name);
				delete node;
			}
			return;
		}
	} DestroyServiceModuleTree(this, m_serviceModuleRoot);

	(void)DestroyServiceModuleTree;

	this->m_serviceModuleRoot = 0;

	struct StateNameTreeDestroyer
	{	
		StateNameTreeDestroyer(KernelImpl * const This, KernelImpl::StateNameTree * node)
		{
			PERFCOUNTER("KernelImpl::~KernelImpl::StateNameTreeDestroyer");

			if (node != 0)
			{
				StateNameTreeDestroyer DestroyLeft(This, node->lleaf);
				StateNameTreeDestroyer DestroyRight(This, node->rleaf);

				(void)DestroyLeft;
				(void)DestroyRight;

				Util::Util_FreeString(node->name);
				delete node;
			}
			return;
		}
	} DestroyStateNameTree(this, m_stateNameRoot);

	(void)DestroyStateNameTree;

	m_stateNameRoot = 0;

	if (m_serviceModuleDiffList != 0)
	{
		for (int index = 0; index < (m_maxCountOfState * m_maxCountOfState); index++)
		{
			if (m_serviceModuleDiffList[index].list != 0)
			{
				delete[] m_serviceModuleDiffList[index].list;
			}
		}
		delete[] m_serviceModuleDiffList;
		m_serviceModuleDiffList = 0;
	}	
	if (m_serviceModuleCatalogId != 0)
	{
		delete[] m_serviceModuleCatalogId;
		m_serviceModuleCatalogId = 0;
	}
	if (m_serviceModuleStateTable != 0)
	{
		delete[] m_serviceModuleStateTable;
		m_serviceModuleStateTable = 0;
	}
	if (m_messageRouterInitState != 0)
	{
		delete[] m_messageRouterInitState;
		m_messageRouterInitState = 0;
	}
	if (m_serviceModuleList != 0) 
	{
		delete[] m_serviceModuleList;
		m_serviceModuleList = 0;
	}
	if (this->m_messageRouterList != 0)
	{
		delete[] m_messageRouterList;
		m_messageRouterList = 0;
	}

	m_maxCountOfMessageRouter = 0;
	m_maxCountOfServiceModule = 0;
	m_maxCountOfState = 0;
	m_countOfMessageRouter = 0;
	m_countOfServiceModule = 0;
	m_countOfState = 0;

	return;
}

IMessageRouter * KernelImpl::PlugMessageRouter(const char * name, IMessageRouter * router)
{
	PERFCOUNTER("KernelImpl::PlugMessageDevicer");

	if (name != 0)
	{
		bool deasil = true;
		Util::CompareResult result = Util::equal;
		KernelImpl::ModuleTree ** slot = &m_messageRouterRoot;
		KernelImpl::ModuleTree *  node =  m_messageRouterRoot;
		while (node != 0)
		{
			result = Util::Util_CompareString(node->name, name);
			if (Util::equal == result)
			{
				if (router == 0)
				{
					// rebuild tree
					if ((node->lleaf != 0) && (node->rleaf != 0))
					{
						if (deasil)
						{
							KernelImpl::ModuleTree * subtree = node->lleaf;
							while (subtree->rleaf != 0) subtree = subtree->rleaf;
							subtree->rleaf = node->rleaf;
							node = node->lleaf;
						}
						else
						{
							KernelImpl::ModuleTree * subtree = node->rleaf;
							while (subtree->lleaf != 0) subtree = subtree->lleaf;
							subtree->lleaf = node->lleaf;
							node = node->rleaf;
						}
					}
					else
					{
						node = (KernelImpl::ModuleTree*) ((int)(node->lleaf) | (int)(node->rleaf));
					}
					
					//cleanup
					KernelImpl::HookList * point = (*slot)->hooks;
					KernelImpl::HookList * nexthook = 0;
					for (; point != 0; point = nexthook)
					{
						if (point->messageRouterHook != 0)
						{
							(*(point->messageRouterHook))((*slot)->messageRouter, router, point->cbdata);
						}
						nexthook = point->next;
						delete point;
					}

					if ((*slot)->name != 0)
					{
						Util::Util_FreeString((*slot)->name);
					}

					IMessageRouter * retval = (*slot)->messageRouter;

					delete (*slot);
					
					*slot = node;
					
					if (retval != 0) retval->Release();

					return retval;
				}
				else
				{
					IMessageRouter * retval = node->messageRouter;
					if (retval != router)
					{
						for (KernelImpl::HookList * point = node->hooks; point != 0; point = point->next)
						{
							if (point->messageRouterHook != 0)
							{
								(*(point->messageRouterHook))(node->messageRouter, router, point->cbdata);
							}
						}
						node->messageRouter = router;

						if (retval != 0) retval->Release();
					}
					return retval;
				}
			}
			else if (Util::less == result)
			{
				deasil = true;
				slot = &(node->rleaf);
				node = node->rleaf;
			}
			else
			{
				deasil = false;
				slot = &(node->lleaf);
				node = node->lleaf;	
			}
		}

		if ((router != 0) &&(0 != ((*slot) = new KernelImpl::ModuleTree())))
		{
			(*slot)->name = Util::Util_AllocString(name);
			(*slot)->lleaf = (*slot)->rleaf = 0;
			(*slot)->hooks = 0;
			(*slot)->messageRouter = router;
		}
	}
	return 0;
}

IServiceModule * KernelImpl::PlugServiceModule(const char * name, IServiceModule * module)
{
	PERFCOUNTER("KernelImpl::PlugServiceModule");

	if (name != 0)
	{
		bool deasil = true;
		Util::CompareResult result = Util::equal;
		KernelImpl::ModuleTree ** slot = &m_serviceModuleRoot;
		KernelImpl::ModuleTree *  node =  m_serviceModuleRoot;
		while (node != 0)
		{
			result = Util::Util_CompareString(node->name, name);
			if (Util::equal == result)
			{	
				if (module == 0)
				{
					// rebuild tree
					if ((node->lleaf != 0) && (node->rleaf != 0))
					{
						if (deasil)
						{
							KernelImpl::ModuleTree * subtree = node->lleaf;
							while (subtree->rleaf != 0) subtree = subtree->rleaf;
							subtree->rleaf = node->rleaf;
							node = node->lleaf;
						}
						else
						{
							KernelImpl::ModuleTree * subtree = node->rleaf;
							while (subtree->lleaf != 0) subtree = subtree->lleaf;
							subtree->lleaf = node->lleaf;
							node = node->rleaf;
						}
					}
					else
					{
						node = (KernelImpl::ModuleTree*) ((int)(node->lleaf) | (int)(node->rleaf));
					}

					//cleanup
					KernelImpl::HookList * point = (*slot)->hooks;
					KernelImpl::HookList * nexthook = 0;
					for (; point != 0; point = nexthook)
					{
						if (point->serviceModuleHook != 0)
						{
							(*(point->serviceModuleHook))((*slot)->serviceModule, module, point->cbdata);
						}
						nexthook = point->next;
						delete point;
					}

					if ((*slot)->name != 0) 
					{
						Util::Util_FreeString((*slot)->name);
					}

					IServiceModule * retval = (*slot)->serviceModule;

					delete (*slot);
					
					*slot = node;

					if (retval != 0) retval->Release();

					return retval;
				}
				else
				{
					IServiceModule * retval = node->serviceModule;
					if (retval != module)
					{
						for (KernelImpl::HookList * point = node->hooks; point != 0; point = point->next)
						{
							if (point->serviceModuleHook != 0)
							{
								(*(point->serviceModuleHook))(node->serviceModule, module, point->cbdata);
							}
						}
						node->serviceModule = module;

						if (retval != 0) retval->Release();
					}
					return retval;
				}
			}
			else if (Util::less == result)
			{
				deasil = true;
				slot = &(node->rleaf);
				node = node->rleaf;
			}
			else
			{
				deasil = false;
				slot = &(node->lleaf);
				node = node->lleaf;
			}
		}

		if ((module != 0) && (0 != ((*slot) = new KernelImpl::ModuleTree())))
		{
			(*slot)->name = Util::Util_AllocString(name);
			(*slot)->lleaf = (*slot)->rleaf = 0;
			(*slot)->hooks = 0;
			(*slot)->serviceModule = module;
		}
	}
	return 0;
}


IMessageRouter * KernelImpl::FindMessageRouter(const char * name) const
{
	PERFCOUNTER("KernelImpl::FindMessageDevice");

	if (name != 0)
	{
		KernelImpl::ModuleTree * node = m_messageRouterRoot;
		Util::CompareResult	result = Util::equal;
		while (node != 0)
		{
			result = Util::Util_CompareString(node->name, name);
			if (Util::equal == result)
			{
				return node->messageRouter;
			}
			else
			{
				node = (Util::less == result ? node->rleaf : node->lleaf);
			}
		}
	}
	return 0;
}

IServiceModule * KernelImpl::FindServiceModule(const char * name) const
{
	PERFCOUNTER("KernelImpl::FindServiceModule");

	if (name != 0)
	{
		KernelImpl::ModuleTree * node = m_serviceModuleRoot;
		Util::CompareResult	result = Util::equal;
		while (node != 0)
		{
			result = Util::Util_CompareString(node->name, name);
			if (Util::equal == result)
			{
				return node->serviceModule;
			}
			else
			{
				node = (Util::less == result ? node->rleaf : node->lleaf);
			}
		}
	}
	return 0;
}

int KernelImpl::GetMessageRouterList(IMessageRouter**& slot) const
{
	PERFCOUNTER("KernelImpl::GetMessageDeviceSlots");

	slot = this->m_messageRouterList;
	return this->m_countOfMessageRouter;

}

int KernelImpl::GetServiceModuleList(IServiceModule**& slot) const
{
	PERFCOUNTER("KernelImpl::GetServiceModuleSlots");

	slot = this->m_serviceModuleList;
	return this->m_countOfServiceModule;
}

int KernelImpl::GetMessageRouterInitStateId(int index) const
{
	PERFCOUNTER("KernelImpl::GetMessageDeviceInitStateId");

	return this->m_messageRouterInitState[index % m_maxCountOfMessageRouter];
}


const StateBits& KernelImpl::GetServiceModuleStateBits(int index) const
{
	PERFCOUNTER("KernelImpl::GetServiceModuleStateBits");

	return this->m_serviceModuleStateTable[index % m_maxCountOfServiceModule];
}

int KernelImpl::GetServiceModuleCatalog(int index) const
{
	PERFCOUNTER("KernelImpl::GetServiceModuleSegment");

	return this->m_serviceModuleCatalogId[index % this->m_maxCountOfServiceModule];
}

int KernelImpl::GetServiceModuleDiffList(int firststateid, int secondstateid, IServiceModule**& list) const
{
	PERFCOUNTER("KernelImpl::GetServiceModuleListDiff");

	if (firststateid != secondstateid)
	{
		if (firststateid < m_maxCountOfState)
		{
			if (secondstateid < m_maxCountOfState)
			{
				list = m_serviceModuleDiffList[firststateid * m_maxCountOfState + secondstateid].list;
				return m_serviceModuleDiffList[firststateid * m_maxCountOfState + secondstateid].count;
			}
			else
			{
				list = m_serviceModuleDiffList[firststateid * m_maxCountOfState + firststateid].list;
				return m_serviceModuleDiffList[firststateid * m_maxCountOfState + firststateid].count;
			}
		}
	}
	list = 0;
	return 0;
}


int KernelImpl::GetStateFromName(const char * statename) const
{
	PERFCOUNTER("KernelImpl::GetStateFromName");

	if (statename != 0)
	{
		KernelImpl::StateNameTree * node = m_stateNameRoot;
		Util::CompareResult	result = Util::equal;
		while (node != 0)
		{
			result = Util::Util_CompareString(node->name, statename);
			if (Util::equal == result)
			{
				return node->stateId;
			}
			else
			{
				node = (Util::less == result ? node->rleaf : node->lleaf);
			}
		}
	}
	return -1;
}


int KernelImpl::AppendStateName(const char * statename)
{
	PERFCOUNTER("KernelImpl::AppendStateName");

	if (statename != 0 && (m_countOfState < m_maxCountOfState))
	{
		KernelImpl::StateNameTree ** hole = &m_stateNameRoot;
		Util::CompareResult	result = Util::equal;
		while ((*hole) != 0)
		{
			result = Util::Util_CompareString((*hole)->name, statename);
			if (Util::equal == result)
			{
				return (*hole)->stateId;
			}
			else
			{
				hole = (Util::less == result ? &((*hole)->rleaf) : &((*hole)->lleaf));
			}
		}
		if (((*hole) = new KernelImpl::StateNameTree) != 0)
		{
			(*hole)->name = Util::Util_AllocString(statename);
			(*hole)->lleaf = (*hole)->rleaf = 0;
			(*hole)->stateId = m_countOfState;
			m_countOfState++;
			return (*hole)->stateId;
		}
	}
	return (unsigned long)(-1);
}

void * KernelImpl::InstallModulePlugHook(const char * name, MessageRouterPlugHook hook, void * cbdata) const
{
	PERFCOUNTER("KernelImpl::InstallDevicePlugHook");

	if (name != 0)
	{
		KernelImpl::ModuleTree * node = m_messageRouterRoot;
		Util::CompareResult	result = Util::equal;
		while (node != 0)
		{
			result = Util::Util_CompareString(node->name, name);
			if (Util::equal == result)
			{
				KernelImpl::HookList * newhook = 0;
				KernelImpl::HookList ** retval = 0;
				if (0 != (newhook = new KernelImpl::HookList()))
				{
					KernelImpl::HookList * point = node->hooks;
					if (point != 0)
					{
						while (point->next != 0) point = point->next;
						point->next = newhook;
						retval = &(point->next);
					}
					else 
					{
						node->hooks = newhook;
						retval = &(node->hooks);
					}
					newhook->prev = point;
					newhook->next = 0;
					newhook->messageRouterHook = hook;
					newhook->cbdata = cbdata;
				}
				return retval;
			}
			else
			{
				node = (Util::less == result ? node->rleaf : node->lleaf);
			}
		}
	}	
	return 0;
}

void * KernelImpl::InstallModulePlugHook(const char * name, ServiceModulePlugHook hook, void * cbdata) const
{
	PERFCOUNTER("KernelImpl::InstallDevicePlugHook");

	if (name != 0)
	{
		KernelImpl::ModuleTree * node = m_serviceModuleRoot;
		Util::CompareResult	result = Util::equal;
		while (node != 0)
		{
			result = Util::Util_CompareString(node->name, name);
			if (Util::equal == result)
			{
				KernelImpl::HookList * newhook = 0;
				KernelImpl::HookList ** retval = 0;
				if (0 != (newhook = new KernelImpl::HookList()))
				{
					KernelImpl::HookList * point = node->hooks;
					if (point != 0)
					{
						while (point->next != 0) point = point->next;
						point->next = newhook;
						retval = &(point->next);
					}
					else 
					{
						node->hooks = newhook;
						retval = &(node->hooks);
					}
					newhook->prev = point;
					newhook->next = 0;
					newhook->serviceModuleHook = hook;
					newhook->cbdata = cbdata;
				}
				return retval;
			}
			else
			{
				node = (Util::less == result ? node->rleaf : node->lleaf);
			}
		}
	}
	return 0;
}

void KernelImpl::UninstallModulePlugHook(void * p) const
{
	PERFCOUNTER("KernelImpl::UninstallModulePlugHook");

	if (p != 0)
	{
		KernelImpl::HookList ** hookslot = (KernelImpl::HookList**)p;
		if ((*hookslot) != 0)
		{
			if ((*hookslot)->prev != 0)
			{
				if ((*hookslot)->prev->next != (*hookslot)) return;
				(*hookslot)->prev->next = (*hookslot)->next;
			}
			if ((*hookslot)->next != 0)
			{
				if ((*hookslot)->next->prev != (*hookslot)) return;
				(*hookslot)->next->prev = (*hookslot)->prev;
			}
			KernelImpl::HookList * drophook =(*hookslot);
			(*hookslot) = (*hookslot)->next;
			delete drophook;
		}
	}
	return;
}

#include "LogDevice.h"
void KernelImpl::OutputConsole(const char * fmt ...) const
{
	PERFCOUNTER("KernelImpl::OutputConsole");

	va_list args;
	va_start(args, fmt);
	PrivateUtil::LogDevice::Instance().Outputln(PrivateUtil::OUTLEVEL_LOG, fmt, args);
	va_end(args);
	return;
}

